<?php

namespace App\Services\Stock;

use App\Enum;
use App\Models\Stock\ProductStock;
use App\Models\Stock\ProductStockLog;
use App\Services\BaseService;

class ProductStockService extends BaseService
{
    protected $inStorageId;//入仓仓库ID
    protected $outStorageId;//出仓仓库ID

    protected $inProductStocks;//入仓库存数据集
    protected $outProductStocks;//出仓库存数据集

    protected $productItems;//需处理的条目


    /**
     * 初始化数据
     * @param $productItems ['product_id' => 1, 'num' => 1,'price'=>'1','total_price'=>1]
     * @param $outStorageId
     * @param $inStorageId
     * @return $this
     */
    public function initData($productItems, $outStorageId = 0, $inStorageId = 0): ProductStockService
    {
        $this->productItems = $productItems;
        $productIds = $this->productItems->map(function ($item) {
            return $item['product_id'];
        });

        if ($outStorageId) {
            $this->outStorageId = $outStorageId;
            //获取所有出入产品库存的初始数据集
            $this->outProductStocks = ProductStock::whereIn('product_id', $productIds->unique())
                ->where('storage_id', $this->outStorageId)
                ->lockForUpdate()
                ->get();
        }
        if ($inStorageId) {
            $this->inStorageId = $inStorageId;
            //获取所有入库产品库存的初始数据集
            $this->inProductStocks = ProductStock::whereIn('product_id', $productIds->unique())
                ->where('storage_id', $this->inStorageId)
                ->lockForUpdate()
                ->get();
        }

        return $this;

    }


    /**
     * 处理条目数据
     * @param $item
     * @param $storageId
     * @param $mode
     * @param $type
     * @return bool
     */
    protected function handleItemData($item, $storageId, $mode, $type): bool
    {
        if ($mode == Enum::PRODUCT_STOCK_LOG_MODE_ADD) {
            $productStock = $this->inProductStocks->where('product_id', $item['product_id'])->first();
            if (!$productStock) {
                $data = array();
                $data['product_id'] = $item['product_id'];
                $data['storage_id'] = $this->inStorageId;
                $data['num'] = 0;
                $data['cost_price'] = 0.00;
                $data['total_cost_price'] = 0.00;
                $productStock = ProductStock::create($data);
                $this->inProductStocks->push($productStock);
            }
        } else {
            //            Enum::PRODUCT_STOCK_LOG_MODE_SUB
            $productStock = $this->outProductStocks->where('product_id', $item['product_id'])->first();
        }

        //获取当前库存结果
        $currentProductStock = $this->getCurrentProductStockResult($productStock, $item, $mode);
        //构造转移入库记录
        $logData = $this->makeLogData($item, $productStock, $currentProductStock, $storageId, $mode, $type);
        ProductStockLog::create($logData);//追加记录

        //因为单价是四舍五入的了,所以操作原总价和原数量，不使用原单价
        $productStock['num'] = $currentProductStock['num'];
        $productStock['cost_price'] = $currentProductStock['cost_price'];
        $productStock['total_cost_price'] = $currentProductStock['total_cost_price'];
        return $productStock->save();//更新产品库存

    }


    /*
     * 获取当前产品库存结果
     * */
    protected function getCurrentProductStockResult($origin, $change, $mode = 'ADD'): array
    {
        if ($mode == Enum::PRODUCT_STOCK_LOG_MODE_ADD) {
            $currentNum = $origin['num'] + $change['num'];
            $currentTotalCostPrice = $origin['total_cost_price'] + $change['total_price'];
        } else {
            //mode= Enum::PRODUCT_STOCK_LOG_MODE_SUB
            $currentNum = $origin['num'] - $change['num'];
            $currentTotalCostPrice = $origin['total_cost_price'] - $change['total_price'];
        }
        //因为单价是四舍五入的了,所以操作原总价和原数量，不使用原单价
        $currentCostPrice = cal_price($currentTotalCostPrice, $currentNum);

        return [
            'num' => $currentNum,
            'cost_price' => $currentCostPrice,
            'total_cost_price' => $currentTotalCostPrice
        ];

    }


    /*
     * 构造库存日志记录
     * */
    protected function makeLogData($item, $originProductStock, $currentProductStock, $storageId, $mode, $type): array
    {
        return [
            'product_id' => $item['product_id'],
            'storage_id' => $storageId,
            'mode' => $mode,
            'type' => $type,
            'original_num' => $originProductStock['num'],
            'original_cost_price' => $originProductStock['cost_price'],
            'move_num' => $item['num'],
            'move_price' => $item['price'],
            'move_total_price' => $item['total_price'],
            'current_num' => $currentProductStock['num'],
            'current_cost_price' => $currentProductStock['cost_price'],
            'current_total_cost_price' => $currentProductStock['total_cost_price'],
        ];

    }


    /**
     * 采购入库库存单处理
     * @return mixed
     */
    public function handlePurchaseIn()
    {
        return $this->productItems->map(function ($item) {
            $this->handleItemData($item, $this->inStorageId, Enum::PRODUCT_STOCK_LOG_MODE_ADD, Enum::PRODUCT_STOCK_LOG_TYPE_PURCHASE_IN);
        });
    }


    /**
     * 采购退货库存单处理
     * @return mixed
     */
    public function handlePurchaseReturn()
    {
        return $this->productItems->map(function ($item) {
            $this->handleItemData($item, $this->inStorageId, Enum::PRODUCT_STOCK_LOG_MODE_SUB, Enum::PRODUCT_STOCK_LOG_TYPE_PURCHASE_RETURN);
        });
    }

    /**
     * 销售订单处理
     * @return mixed
     */
    public function handleSaleOut()
    {
        return $this->productItems->map(function ($item) {
            $this->handleItemData($item, $this->outStorageId, Enum::PRODUCT_STOCK_LOG_MODE_SUB, Enum::PRODUCT_STOCK_LOG_TYPE_SALE_OUT);
        });
    }

    /**
     * 销售订单退货处理
     * @return mixed
     */
    public function handleSaleReturn()
    {
        return $this->productItems->map(function ($item) {
            $this->handleItemData($item, $this->inStorageId, Enum::PRODUCT_STOCK_LOG_MODE_ADD, Enum::PRODUCT_STOCK_LOG_TYPE_SALE_RETURN);
        });
    }

    /**
     * 转移库存单处理
     * @return mixed
     */
    public function handleTransfer()
    {
        return $this->productItems->map(function ($item) {
            $this->handleItemData($item, $this->inStorageId, Enum::PRODUCT_STOCK_LOG_MODE_ADD, Enum::PRODUCT_STOCK_LOG_TYPE_TRANSFER_IN);
            $this->handleItemData($item, $this->outStorageId, Enum::PRODUCT_STOCK_LOG_MODE_SUB, Enum::PRODUCT_STOCK_LOG_TYPE_TRANSFER_OUT);
        });
    }

    /**
     * 库存盘点处理
     * @return mixed
     */
    public function handleStockCheck()
    {
        return $this->productItems->map(function ($item) {
            if ($item['mode'] == Enum::PRODUCT_STOCK_LOG_MODE_ADD) {
                $this->handleItemData($item, $this->inStorageId, Enum::PRODUCT_STOCK_LOG_MODE_ADD, Enum::PRODUCT_STOCK_LOG_TYPE_STOCK_CHECK);

            } else {
//                $item['mode']==Enum::PRODUCT_STOCK_LOG_MODE_SUB
                $this->handleItemData($item, $this->outStorageId, Enum::PRODUCT_STOCK_LOG_MODE_SUB, Enum::PRODUCT_STOCK_LOG_TYPE_STOCK_CHECK);

            }
        });
    }


}